import config from '../config/main.js';
import mysql from 'mysql2';


function middleware(_app) {
    const app = _app;
    const log = app.log.getLogger('[mysqlm]');

    const methods = [
        'query',
        'execute',
    ];

    function wrap(fn, ctx) {
        return (...args) => {
            const f = (done) => {
                args.push(done);
                fn.apply(ctx, args);
            };
            return f;
        };
    }

    function wrapConnection(_conn) {
        const conn = _conn;
        if (conn.coWrapped) {
            return conn;
        }
        conn.coWrapped = true;
        methods.forEach((name) => {
            conn[name] = wrap(conn[name], conn);
        });
        return conn;
    }

    function createPool(opts) {
        const pool = mysql.createPool(opts);
        const getConn = pool.getConnection;
        const wrappedGetConnection = () => {
            const f = (done) => {
                getConn.call(pool, (err, conn) => {
                    if (err) return done(err);
                    return done(null, wrapConnection(conn));
                });
            };
            return f;
        };
        pool.getConnection = wrappedGetConnection;
        return pool;
    }

    const dbm = {};
    const pool = createPool(config.mysql);

    log.info('mysql connect success ...');

    dbm.query = function* gen(sql, params) {
        const db = yield pool.getConnection();
        const rows = yield db.query(sql, params);
        db.release();
        return rows[0];
    };

    dbm.execute = function* exe(sql, params) {
        const db = yield pool.getConnection();
        const rows = yield db.execute(sql, params);
        db.release();
        return rows[0];
    };

    app.mysql = dbm;

    return function* dispatch(next) {
        this.mysql = dbm;
        yield next;
    };
}

export default middleware;

